package com.soc.auth.exception;

import com.soc.auth.enumes.ResponseStatusEnum;
import com.soc.auth.utils.ErrorUtil;
import com.soc.auth.utils.ResultResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 全局系统异常处理
 **/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 前端提交的方式为json格式有效
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public <T> ResultResponse<T> handler(MethodArgumentNotValidException e) {
        log.error("MethodArgumentNotValidException:{}", e.getMessage());
        // 将所有参数错误都拼接成字符串
        String errorMsg = e.getBindingResult().getAllErrors()
                .stream()
                .map(file -> {
                    FieldError fieldError = (FieldError) file;
                    return ErrorUtil.parameterErrorFormat(fieldError.getField(), fieldError.getDefaultMessage());
                })
                .collect(Collectors.joining());
        return ResultResponse.fail(ResponseStatusEnum.ParameterValidError, errorMsg);
    }

    // 仅对于表单提交有效，对于以json格式提交将会失效
    @ExceptionHandler(BindException.class)
    public <T> ResultResponse<T> handler(BindException e) {
        log.error("BindException:{}", e.getMessage());
        String errorMsg = e.getBindingResult().getAllErrors()
                .stream()
                .map(file -> {
                    FieldError fieldError = (FieldError) file;
                    return ErrorUtil.parameterErrorFormat(fieldError.getField(), fieldError.getDefaultMessage());
                })
                .collect(Collectors.joining());
        return ResultResponse.fail(ResponseStatusEnum.ParameterValidError, errorMsg);
    }

    // 处理单个参数校验失败抛出的异常
    @ExceptionHandler(ConstraintViolationException.class)
    public <T> ResultResponse<T> handler(ConstraintViolationException e) {
        log.error("ConstraintViolationException:{}", e.getMessage());
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String errorMsg = constraintViolations
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining());
        log.error(errorMsg);
        return ResultResponse.fail(ResponseStatusEnum.ParameterValidError, errorMsg);
    }


    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(IllegalArgumentException.class)
    public <T> ResultResponse<T> handleIllegalArgumentException(IllegalArgumentException e) {
        log.error("非法参数异常，异常原因：{}", e.getMessage(), e);
        return ResultResponse.fail(e.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public <T> ResultResponse<T> handler(BusinessException e) {
        log.error("出现业务异常：" + e.getMessage());
        return ResultResponse.fail(ResponseStatusEnum.Error_Req, e.getMessage());
    }

//    @ExceptionHandler(Exception.class)
//    public <T> ResultResponse<T> handler(Exception e) {
//        return ResultResponse.fail(ResponseStatusEnum.InnerServerError);
//    }
}
